'use strict'

// sms
const URL_SMS = 'https://gyytz.market.alicloudapi.com/sms/smsSend'
const AUTHORIZATION = 'APPCODE 48b7680d8be64610a5d2ec04d8825fff'
const SMS_SIGN_ID = '698a4ca36d4f49bca5aa3d0e97319e2e'
const TEMPLATE_ID = 'a112d6f143054fbe87392b9b22df9ea3'

// email
const HOST = 'smtp.163.com'
const SENDER_USERNAME = 'dtc_book_corner@163.com'
const SENDER_AUTH_CODE = 'GXZHXTZSSKBIFSYP'
const SSL_PORT = 465

// vx message
const APP_ID = 'wx34925f2944bb0472'
const APP_SECRET = 'a7521984cb51004c44b39551dc590248'
const URL_GET_ACCESS_TOKEN = 'https://api.weixin.qq.com/cgi-bin/token'
const URL_SEND_MESSAGE = 'https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token='
let ACCESS_TOKEN = ''

/*
    template
    index 0 邮件标题
    index 1-2 即将到期
    index 3 已逾期
 */
const TEMPLATE = [
    '图书催还通知',
    '3日后即将到期，请及时续借或归还，谢谢！',
    '1日后即将到期，请及时续借或归还，谢谢！',
    '已逾期，请及时续借或归还，谢谢！'
]
const TEMPLATE_ID_VX = [
    '',
    'SqlXSDlBiaYv4KDDtz3BNPfb0-X_mNYDt_sV1OzhiZg',
    'sVW1LT6sDt33czuxqq4qq0tUslwhwYPUgVN5wjYeod4',
    'g4RMcRLwZxfvdtUFuxmGVis46XZAaeualEv6-vRAQEs'
]
const MESSAGE_FIELD = [
    [],
    ['thing1', 'time3', 'thing4'],
    ['thing3', 'date1', 'thing4'],
    ['thing1', 'time4', 'thing5']
]

// dependencies
const vkmail = require('vk-mail')

exports.main = async (event, context) => {
    // 获取AccessToken
    await getAccessToken()
    // 获取数据库客户端
    let dbJQL = uniCloud.databaseForJQL({event, context})
    // 获取所有状态为"借阅中"借阅记录
    let records = await getRecordsInfo(dbJQL)
    // 遍历所有”借阅中“记录，推送消息
    records.forEach(record => {
        let {status} = getBorrowStatus(record.createDate, record.borrowTime)
        let user = record.userId[0]
        let book = record.bookId[0]
        if (status) push(user, book, record, status)
    })
}

/**
 * 获取AccessToken
 */
async function getAccessToken() {
    ({access_token: ACCESS_TOKEN} = (await uniCloud.httpclient.request(URL_GET_ACCESS_TOKEN, {
        method: 'GET',
        dataType: 'json',
        dataAsQueryString: true,
        data: {
            grant_type: 'client_credential',
            appid: APP_ID,
            secret: APP_SECRET
        }
    })).data)
}

/**
 * 获取获取所有状态为"借阅中"借阅记录
 * @param dbJQL
 * @return {Promise<*>}
 */
async function getRecordsInfo(dbJQL) {
    let record = dbJQL.collection('record').where('status == "borrow"').field('bookId,userId,createDate,borrowTime').getTemp()
    let book = dbJQL.collection('book').field('_id,name,cover').getTemp()
    let user = dbJQL.collection('user').field('_id,name,tel,email,openId,notifySms,notifyEmail,notifyMp').getTemp()
    return (await dbJQL.collection(record, book, user).get()).data
}

/**
 * 判断借阅状态
 * @param borrowDate 借阅时间
 * @param duration 借阅时长
 * @return {{status}} day=剩余或天数 status={0:正常借阅状态,1:一天之内（包含一天）,2:三天之内（包含三天）,3:逾期}
 */
function getBorrowStatus(borrowDate, duration) {
    let oneDay = 86400000
    let threeDays = 86400000 * 3
    let now = Date.now()
    // 归还日期
    let returnDate = borrowDate + duration * oneDay
    // 逾期
    if (now - returnDate > 0)
        return {status: 3}
    // 一天之内（包含一天）
    else if (returnDate - now <= oneDay)
        return {status: 2}
    // 三天之内（包含三天）
    else if (returnDate - now <= threeDays)
        return {status: 1}
    // 正常借阅借阅
    else return {status: 0}
}


/**
 * 推送消息
 * @param userInfo 用户信息
 * @param bookInfo 图书信息
 * @param record 借阅记录信息
 * @param status 借阅状态
 */
function push(userInfo, bookInfo, record, status) {
    if (userInfo.notifySms) sendSMS(userInfo.tel, userInfo.name, bookInfo.name, TEMPLATE[status])
    if (userInfo.notifyEmail) sendEmail(userInfo.email, TEMPLATE[0], getEmailHTML(userInfo, bookInfo, status))
    if (userInfo.notifyMp) sendMessage(bookInfo.name, getReturnDate(record.createDate, record.borrowTime), userInfo.openId, status)
}

/**
 * 获取邮件模板
 * @param userInfo 用户信息
 * @param bookInfo 图书信息
 * @param status 借阅状态
 */
function getEmailHTML(userInfo, bookInfo, status) {
    const {email} = require('./email')
    return email
        .replace('**username**', userInfo.name)
        .replace('**book**', bookInfo.name)
        .replace('**content**', TEMPLATE[status])
        .replace('**cover**', bookInfo.cover)
}

/**
 * 获取归还时间
 * @param borrowDate 开始借阅时间
 * @param duration 借阅时长
 * @return {string} “xx年xx月xx日”形式的时间字符串
 */
function getReturnDate(borrowDate, duration) {
    let returnDate = new Date((borrowDate + duration * 86400000))
    let Y = returnDate.getFullYear() + '年'
    let M = (returnDate.getMonth() + 1 < 10 ? '0' + (returnDate.getMonth() + 1) : returnDate.getMonth() + 1) + '月'
    let D = (returnDate.getDate() < 10 ? '0' + returnDate.getDate() : returnDate.getDate()) + '日'
    return Y + M + D
}

/**
 * 发送短信
 * @param mobile 手机号
 * @param username 用户名
 * @param book 书名
 * @param content 模板内容
 */
function sendSMS(mobile, username, book, content) {
    uniCloud.httpclient.request(URL_SMS, {
        method: 'POST',
        dataType: 'json',
        dataAsQueryString: true,
        headers: {
            Authorization: AUTHORIZATION
        },
        data: {
            mobile,
            param: `**username**:${username},**book**:${book},**content**:${content}`,
            smsSignId: SMS_SIGN_ID,
            templateId: TEMPLATE_ID
        }
    })
}

/**
 * 发送邮件
 * @param email 手机号
 * @param subject 主题
 * @param html 邮件正文
 */
function sendEmail(email, subject, html) {
    let emailService = vkmail.createTransport({
        host: HOST,
        port: SSL_PORT,
        secure: true,
        auth: {
            user: SENDER_USERNAME,
            pass: SENDER_AUTH_CODE
        }
    })
    emailService.sendMail({
        from: SENDER_USERNAME,
        to: email,
        cc: SENDER_USERNAME,
        subject,
        html
    })
}

/**
 * 推送消息
 * @param bookName 书名
 * @param returnDate 归还日期
 * @param touser 用户openId
 * @param status 借阅状态
 */
function sendMessage(bookName, returnDate, touser, status) {
    uniCloud.httpclient.request(URL_SEND_MESSAGE + ACCESS_TOKEN, {
        method: 'POST',
        dataAsQueryString: false,
        contentType: 'json',
        data: {
            touser,
            template_id: TEMPLATE_ID_VX[status],
            lang: 'zh_CN',
            page: 'Switch',
            data: {
                [MESSAGE_FIELD[status][0]]: {
                    value: `《${bookName}》`
                },
                [MESSAGE_FIELD[status][1]]: {
                    value: returnDate
                },
                [MESSAGE_FIELD[status][2]]: {
                    value: TEMPLATE[status]
                }
            }
        }
    })
}
